package com.atguigu.gmall.item.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.item.service.ItemService;
import com.atguigu.gmall.list.feign.SearchFeign;
import com.atguigu.gmall.model.product.BaseCategoryView;
import com.atguigu.gmall.model.product.SkuInfo;
import com.atguigu.gmall.model.product.SpuSaleAttr;
import com.atguigu.gmall.product.feign.ProductFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Consumer;

/**
 * @author 搭忆长安
 * @version 1.0
 * @date 2021年07月01日 20:45
 * @ClassName:ItemsServiceImpl
 * @Description: TODO
 */
@Service
public class ItemServiceImpl implements ItemService {

    @Autowired
    private ProductFeign productFeign;
    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;
    @Autowired
    private SearchFeign searchFeign;
    /**
     * 获取商品的详细信息
     *
     * @param skuId
     * @return
     */
    @Override
    public Map<String, Object> getSkuInfo(Long skuId) {
        //最终的合并结果
        Map<String, Object> result = new Hashtable<>();
         //异步查询基本信息和图片列表
        CompletableFuture<SkuInfo> skuInfoCompletableFuture = CompletableFuture.supplyAsync(() -> {
            //查询基本信息和图片列表
            //查询基本信息和图片列表
            SkuInfo skuInfo = productFeign.getSkuInfo(skuId);
            //保存结果
            result.put("skuInfo",skuInfo);
            //返回
            return skuInfo;
        }, threadPoolExecutor);
        //并行执行分类信息查询
        CompletableFuture<Void> categoryView = skuInfoCompletableFuture.thenAcceptAsync(new Consumer<SkuInfo>() {
            @Override
            public void accept(SkuInfo skuInfo) {
                //获取spuid
                Long spuId = skuInfo.getSpuId();
                //获取分类信息
                BaseCategoryView category = productFeign.getCategory(skuInfo.getCategory3Id());
                //保存结果
                result.put("categoryView", category);
            }
        },threadPoolExecutor);

        //并行获取价格信息
        CompletableFuture<Void> price = skuInfoCompletableFuture.thenAcceptAsync(new Consumer<SkuInfo>() {
            @Override
            public void accept(SkuInfo skuInfo) {
                //查询价格信息
                BigDecimal price = productFeign.getPrice(skuId);
                //保存结果
                result.put("price", price);

            }
        },threadPoolExecutor);
        //并行查询销售属性
        CompletableFuture<Void> spuSaleAttrList = skuInfoCompletableFuture.thenAcceptAsync(new Consumer<SkuInfo>() {
            @Override
            public void accept(SkuInfo skuInfo) {
                //通过skuid和spuid查询当前商品的销售属性和当前spu的所有的销售属性
                List<SpuSaleAttr> saltAttrBySpuAndSku = productFeign.getSaleAttrBySpuAndSku(skuId, skuInfo.getId());
                //保存
                result.put("spuSaleAttrList", saltAttrBySpuAndSku);
            }
        },threadPoolExecutor);

        //并行键值对
        CompletableFuture<Void> valuesSkuJson = skuInfoCompletableFuture.thenAcceptAsync(new Consumer<SkuInfo>() {
            @Override
            public void accept(SkuInfo skuInfo) {
                Map skuSaleAttrListBySpuId = productFeign.getSkuSaleAttrListBySpuId(skuInfo.getId());
                result.put("valuesSkuJson", JSONObject.toJSONString(skuSaleAttrListBySpuId));
            }
        },threadPoolExecutor);
        //同步等待等所有的任务执行完成后
        CompletableFuture.allOf(skuInfoCompletableFuture,//查询基本信息的任务
                categoryView,//查询分类信息的任务
                price,//查询价格的任务
                spuSaleAttrList,//销售属性的任务
                valuesSkuJson).join();//键值对的任务
        //这个商品被浏览了一下，异步记录一次hotscore+1
        CompletableFuture.runAsync(new Runnable() {
            @Override
            public void run() {
                searchFeign.addHotScore(skuId);
            }
        }, threadPoolExecutor);


        //返回
        return result;
    }
}
